﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using Go;
using GoRpc;

namespace ScreenView
{
    public partial class MainForm : Form
    {
        control_strand strand;
        generator _action;

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            textBox_ip.Focus();
            strand = new control_strand(this);
            generator.go(out _action, strand, () => Action(null), delegate ()
            {
                Reset();
            });
        }

        private void button_ip_Click(object sender, EventArgs e)
        {
            _action.stop();
        }

        private void Reset()
        {
            generator.go(out _action, strand, () => Action(textBox_ip.Text), delegate ()
            {
                Reset();
            });
        }

        private async Task Action(string addr)
        {
            string ip = null;
            int port = 0;
            await generator.send_task(delegate ()
            {
                try
                {
                    if (null == addr)
                    {
                        addr = File.ReadAllText("./Address.txt");
                    }
                    string[] addr_ = addr.Split(':');
                    port = int.Parse(addr_[1]);
                    ip = addr_[0];
                }
                catch (Exception) { }
            });
            if (null == ip)
            {
                await generator.hold();
                return;
            }
            textBox_ip.Text = addr;
            while (true)
            {
                socket_tcp socket = new socket_tcp();
                Rpc.Methods methods = new Rpc.Methods();
                Rpc.Session session = new Rpc.Session(strand, socket, methods);
                generator.children refreshChildren = new generator.children();
                try
                {
                    if (await socket.connect(ip, port))
                    {
                        await generator.send_task(() => File.WriteAllText("./Address.txt", addr));
                        int count = 0;
                        refreshChildren.go(async delegate ()
                        {
                            string oldText = this.Text;
                            try
                            {
                                while (true)
                                {
                                    int lastCount = count;
                                    long begin = system_tick.ms;
                                    await generator.sleep(1000);
                                    double time = 1000.0 / (system_tick.ms - begin);
                                    double fps = time * (count - lastCount);
                                    this.Text = $"{fps:0.0} fps";
                                }
                            }
                            finally
                            {
                                this.Text = oldText;
                            }
                        });
                        refreshChildren.go(async delegate ()
                        {
                            Bitmap bitmap1 = null, bitmap2 = null;
                            await session.Call("IO.CaptureScreen", session.OverCallback(async delegate (int width, int height)
                            {
                                Rpc.OverRecv data = Rpc.Session.OverRecv()[0];
                                if (null == bitmap1 || bitmap1.Size != new Size(width, height))
                                {
                                    bitmap1 = new Bitmap(width, height, PixelFormat.Format24bppRgb);
                                }
                                if (null == bitmap2 || bitmap2.Size != new Size(width, height))
                                {
                                    bitmap2 = new Bitmap(width, height, PixelFormat.Format24bppRgb);
                                }
                                Bitmap t = bitmap1;
                                bitmap1 = bitmap2;
                                bitmap2 = t;
                                BitmapData bitmapData = bitmap1.LockBits(new Rectangle { Width = width, Height = height }, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
                                try
                                {
                                    while (!data.Completed)
                                    {
                                        await data.Recv(bitmapData.Scan0, data.Offset, (int)(data.Length - data.Offset));
                                    }
                                }
                                finally
                                {
                                    bitmap1.UnlockBits(bitmapData);
                                }
                                pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
                                pictureBox1.Image = bitmap1;
                                count++;
                            }));
                        });
                        session.Start();
                        await session.Join();
                    }
                }
                finally
                {
                    generator.lock_stop();
                    await refreshChildren.stop();
                    session.Close();
                    generator.unlock_stop();
                }
                await generator.sleep(1000);
            }
        }
    }
}